use std::mem::MaybeUninit;

use serde::Serialize;
use serde_bytes;
use sqlx::{Executor, SqlitePool};
use crate::{cfg, error::AppErr};

static mut POOL: MaybeUninit<SqlitePool> = MaybeUninit::uninit();

mod user;
mod equip;

pub use equip::*;
pub use user::*;

pub async fn init() -> Result<(), AppErr> {
    let url = format!("sqlite://{}?mode=rwc", cfg::DB_PATH);
    let pool = SqlitePool::connect(&url).await?;
    pool.execute(TB_USER).await?;
    pool.execute(TB_EQUIPMENTS).await?;
    pool.execute(TB_SPECIAL).await?;
    pool.execute(TB_EQUIP_IMAGE).await?;

    unsafe {
        POOL.write(pool);
    }

    Ok(())
}

#[inline(always)]
pub fn get_pool() -> &'static SqlitePool {
    unsafe {
        POOL.assume_init_ref()
    }
}

/**
 * 人员表
 */
pub const TB_USER: &'static str = r#"
    CREATE TABLE IF NOT EXISTS tb_user (
        id INTEGER PRIMARY KEY, 
        game_id TEXT UNIQUE, 
        game_name TEXT NOT NULL, 
        faction TEXT NOT NULL, 
        profession TEXT NOT NULL, 
        character TEXT NOT NULL, 
        notes TEXT NOT NULL 
    )
"#;

#[derive(Debug, Serialize)]
pub struct TbUser {
    pub id: i64,
    pub game_id: String,
    pub game_name: String,
    pub faction: String, // 门派
    pub profession: String, // 职业
    pub character: String, // 角色
    pub notes: String, 
}

/**
 * 装备信息表
 */
pub const TB_EQUIPMENTS: &'static str = r#"
    CREATE TABLE IF NOT EXISTS tb_equipments (
        id INTEGER PRIMARY KEY, 
        user_id INTEGER NOT NULL, 
        equip_type INTEGER NOT NULL,
        level INTEGER NOT NULL 
    )
"#;
pub struct TbEquipments {
    pub id: i64,
    pub user_id: i64,
    pub equip_type: u8, // 装备类型
    pub level: u8, // 宝石段数
}

/**
 * 装备特技
 */
pub const TB_SPECIAL: &'static str = r#"
    CREATE TABLE IF NOT EXISTS tb_special (
        id INTEGER PRIMARY KEY, 
        equip_id INTEGER NOT NULL, 
        name TEXT NOT NULL
    )
"#;
pub struct TbSpecial {
    pub id: i64,
    pub equip_id: i64,
    pub name: String,
}

/**
 * 装备截图
 */
pub const TB_EQUIP_IMAGE: &'static str = r#"
    CREATE TABLE IF NOT EXISTS tb_equip_image (
        id INTEGER PRIMARY KEY,
        equip_id INTEGER NOT NULL, 
        data BLOB NOT NULL, 
        notes TEXT NOT NULL
    )
"#;
#[derive(Debug, Serialize)]
pub struct TbEquipImage {
    pub id: i64,
    pub equip_id: i64,

    #[serde(with = "serde_bytes")]
    pub data: Box<[u8]>,

    pub notes: String,
}



